﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Reflection;
using System.Web;
using System.Web.UI;

namespace Dala.Utilities
{
    /// <summary>
    /// Export to csv format utility
    /// </summary>
    public class CsvUtility
    {
        /// <summary>
        /// Take DataTable as input and export to physical csv file
        /// </summary>
        /// <param name="table">DataTable to export</param>
        /// <param name="filename">csv file name</param>
        /// <param name="seperateChar">character to use as scv separator</param>
        public static void ExportDataTableToCSV(DataTable table, string filename, string seperateChar)
        {
            StreamWriter sr = null;
            Int32 success = 0;
            try
            {
                sr = new StreamWriter(filename);
                string seperator = "";
                StringBuilder builder = new StringBuilder();

                foreach (DataColumn col in table.Columns)
                {
                    builder.Append(seperator).Append(col.ColumnName);
                    seperator = seperateChar;
                }

                sr.WriteLine(builder.ToString());

                foreach (DataRow row in table.Rows)
                {
                    seperator = "";
                    builder = new StringBuilder();
                    foreach (DataColumn col in table.Columns)
                    {
                        ///Fields with embedded commas must be delimited with double-quote characters.
                        ///A field that contains embedded line-breaks must be surounded by double-quotes
                        if (RegExUtility.HasComma(row[col.ColumnName].ToString()) || RegExUtility.HasLineBreaks(row[col.ColumnName].ToString()))
                        {
                            builder.Append(seperator).Append("\"" + row[col.ColumnName] + "\"");
                        }
                        else
                        {
                            builder.Append(seperator).Append(row[col.ColumnName]);
                        }

                        seperator = seperateChar;
                    }
                    ++success;
                    sr.WriteLine(builder.ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            finally { if (sr != null){  sr.Close(); } }

        }

        /// <summary>
        /// Take DataTable as input and export to csv which will be prompt save as dialog
        /// </summary>
        /// <param name="table">DataTable to export</param>
        /// <param name="seperateChar">character to use as scv separator</param>
        public static void ExportDataTableToCSV(DataTable table,string seperateChar)
        {
            Int32 success = 0;
            StringBuilder export = new StringBuilder();
            try
            {
                string seperator = "";
                StringBuilder builder = new StringBuilder();

                foreach (DataColumn col in table.Columns)
                {
                    builder.Append(seperator).Append(col.ColumnName);
                    seperator = seperateChar;
                }

                export.AppendLine(builder.ToString());

                foreach (DataRow row in table.Rows)
                {
                    seperator = "";
                    builder = new StringBuilder();
                    foreach (DataColumn col in table.Columns)
                    {
                        ///Fields with embedded commas must be delimited with double-quote characters.
                        ///A field that contains embedded line-breaks must be surounded by double-quotes
                        if (RegExUtility.HasComma(row[col.ColumnName].ToString()) || RegExUtility.HasLineBreaks(row[col.ColumnName].ToString()))
                        { 
                            builder.Append(seperator).Append("\""+row[col.ColumnName]+"\""); 
                        }
                        else 
                        { 
                            builder.Append(seperator).Append(row[col.ColumnName]); 
                        }
                        seperator = seperateChar;
                    }
                    ++success;
                    export.AppendLine(builder.ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.Buffer = true;
            HttpContext.Current.Response.ContentType = "application/CSV";
            HttpContext.Current.Response.AppendHeader("content-disposition", "attachment;filename=FileName.csv");
            HttpContext.Current.Response.Charset = "";
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Write(export.ToString());
            HttpContext.Current.Response.End();

        }

        /// <summary>
        /// Take object List as input and export to csv which will be prompt save as dialog
        /// </summary>
        /// <typeparam name="T">Type of object</typeparam>
        /// <param name="listToExport">Object list to export</param>
        /// <param name="seperateChar">character to use as scv separator</param>
        public static void ExportListToCSV<T>(List<T> listToExport, string seperateChar)
        {
            Int32 success = 0;
            StringBuilder export = new StringBuilder();
            try
            {               
                string seperator = "";
                StringBuilder builder = new StringBuilder();
                PropertyInfo[] fieldInfo = listToExport[0].GetType().GetProperties();
                foreach (PropertyInfo col in fieldInfo)
                {
                    if (col.PropertyType != typeof(EntityKey) && col.PropertyType != typeof(EntityState))
                    {
                        builder.Append(seperator).Append(col.Name);
                        seperator = seperateChar;
                    }
                }
                export.AppendLine(builder.ToString());
                foreach (T dataItem in listToExport)
                {
                    PropertyInfo[] allProperties = dataItem.GetType().GetProperties();
                    seperator = "";
                    StringBuilder builderTmp = new StringBuilder();
                    foreach (PropertyInfo thisProperty in allProperties)
                    {
                        if (thisProperty.PropertyType != typeof(EntityKey) && thisProperty.PropertyType != typeof(EntityKey))
                        {
                            object value = thisProperty.GetValue(dataItem, null);
                            String propetyValue = (value == null ? String.Empty : value.ToString());
                            builderTmp.Append(seperator).Append(propetyValue);
                            seperator = seperateChar;
                        }
                    }
                    ++success;
                    export.AppendLine(builderTmp.ToString());                   
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

           // finally { if (sr != null) { sr.Close(); } }

           HttpContext.Current.Response.Clear();
           HttpContext.Current.Response.Buffer = true;
           HttpContext.Current.Response.ContentType = "application/CSV";
           HttpContext.Current.Response.AppendHeader("content-disposition", "attachment;filename=FileName.csv");
           HttpContext.Current.Response.Charset = "";
           HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
           HttpContext.Current.Response.Write(export.ToString());
           HttpContext.Current.Response.End();

        }       
    }
}
